home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / tcomm50.zip / QUICKB.C < prev    next >
Text File  |  1988-09-24  |  25KB  |  1,123 lines

  1. /*
  2. **  QUICKB.C - Quick B Protocol Support routines
  3. **
  4. **    converted to C by Paul M. Resch
  5. **  adapted to LiteComm(tm) ToolBox by Information Technology, Ltd.
  6. */
  7.  
  8. /*
  9. ** This module implements the B-Protocol Functions.
  10. **
  11. ** bp_DLE should be invoked whenever a <DLE> is received.
  12. ** bp_ENQ should be called whenever an <ENQ> is received.
  13. ** bp_ESC_I should be called when the sequence <ESC><I> is received.
  14. **
  15. ** This source was originally derived from QUICKB.INC, written by
  16. ** Russ Ranshaw, CompuServe Incorporated.
  17. **
  18. */
  19.  
  20. #include "litecomm.h"
  21. #include "litexm.h"
  22. #include <vcstdio.h>
  23.  
  24. #include <dos.h>
  25.  
  26. #ifdef M_I86
  27. #include <stdlib.h>
  28. #include <fcntl.h>
  29. #include <io.h>
  30. #include <sys\types.h>
  31. #include <sys\stat.h>
  32. #endif
  33.  
  34. #ifdef __TURBOC__
  35. #include <conio.h>
  36. #include <fcntl.h>
  37. #include <io.h>
  38. #include <stat.h>
  39. #endif
  40.  
  41. extern unsigned int port;                /* defined in TTL main */
  42.  
  43. #define    TRUE    1
  44. #define    FALSE    0
  45.  
  46. #undef DLE
  47. #undef NAK
  48.  
  49. #define    DLE        16
  50. #define    ETX        03
  51. #define    NAK        21
  52. #define    ENQ        05
  53. #define    CR        0x0D
  54. #define    LF        0x0A
  55. #define    MAX_BUF_SIZE    1032            /* Largest data block we can handle */
  56. #define    MAX_SA        2                    /* Maximum number of waiting packets */
  57.  
  58. #define    DEF_BUF_SIZE    511                /* Default data block */
  59. #define    DEF_WS        1                    /* I can send 2 packets ahead */
  60. #define    DEF_WR        1                    /* I can receive single send-ahead */
  61. #define    DEF_BS        8                    /* I can handle 1024 bytes */
  62. #define    DEF_CM        1                    /* I can handle CRC */
  63. #define    DEF_DQ        1                    /* I can handle non-quoted NUL */
  64.  
  65. #define    MAX_ERRORS    10
  66.  
  67. #define incr_seq(v)    (v == 9 ? 0 : v+1)    /* macro to incr seq number */
  68. #define incr_SA(v)  (v == MAX_SA ? 0 : v + 1 )
  69. #define    send_enq() (lc_put(port, ENQ))
  70.  
  71.  
  72. /*
  73. ** Receive States
  74. */
  75.  
  76. #define    R_GET_DLE        0
  77. #define    R_GET_B            1
  78. #define    R_GET_SEQ        2
  79. #define    R_GET_DATA        3
  80. #define    R_GET_CHECKSUM    4
  81. #define    R_SEND_ACK        5
  82. #define    R_TIMED_OUT        6
  83. #define    R_SUCCESS        7
  84.  
  85. /*
  86. ** Send States
  87. */
  88.  
  89. #define    S_GET_DLE    1
  90. #define    S_GET_NUM    2
  91. #define    S_HAVE_ACK    3
  92. #define    S_GET_PACKET    4
  93. #define    S_TIMED_OUT    5
  94. #define    S_SEND_NAK    6
  95. #define    S_SEND_ENQ    7
  96. #define    S_SEND_DATA    8
  97.  
  98. typedef    struct    PACKETB
  99. {
  100.     int        seq;                        /* Packet's sequence number */
  101.     int        num;                        /* Number of bytes in packet */
  102.     unsigned char buf[MAX_BUF_SIZE];     /* Actual packet data */
  103. } PACKET;
  104.  
  105. static    PACKET    SA_Buf[MAX_SA+1];          /* Send-ahead buffers */
  106.  
  107. /*
  108. ** Table of control characters that need to be masked
  109. */
  110.  
  111. static    char mask_table[] =
  112. {
  113.     0, 0, 0, 1, 0, 1, 0, 0,               /* NUL SOH SOB ETX EOT ENQ SYN BEL */
  114.     0, 0, 0, 0, 0, 0, 0, 0,                /* BS  HT  LF  VT  FF  CR  SO  SI  */
  115.     1, 1, 0, 1, 0, 1, 0, 0,                /* DLE DC1 DC2 DC3 DC4 NAK ^V  ^W  */
  116.     0, 0, 0, 0, 0, 0, 0, 0                /* CAN ^Y  ^Z  ESC ?   ?   ?   ?   */
  117. };
  118.  
  119. static    char    hex_digit[] = "0123456789ABCDEF";
  120.  
  121. static    int    seq_num;                    /* Current Sequence Number */
  122. static    int    lchecksm;                    /* May hold CRC */
  123. static    int    r_size;                        /* size of receiver buffer */
  124. static    unsigned int s_counter,
  125.                      r_counter;
  126. static    int    timed_out;                    /* we timed out before receiving */
  127. static    int    cchar;                        /* current character */
  128. static    int    masked;                        /* TRUE if ctrl character 'masked' */
  129. static    int    packet_received;            /* True if a packet was received */
  130. static    unsigned char r_buffer[MAX_BUF_SIZE];
  131.  
  132. /*
  133. ** Other End's Parameters
  134. */
  135.  
  136. static    char    His_WS;                    /* Sender's Window Send */
  137. static    char    His_WR;                    /* Sender's Window Receive */
  138. static    char    His_BS;                    /* Sender's Block Size */
  139. static    char    His_CM;                    /* Sender's Check Method */
  140.  
  141. /*
  142. ** Negotiated Parameters
  143. */
  144.  
  145. static    char    Our_WS;                    /* Negotiated Window Send */
  146. static    char    Our_WR;                    /* Negotiated Window Receive */
  147. static    char    Our_BS;                    /* Negotiated Block Size */
  148. static    char    Our_CM;                    /* Negotiated Check Method */
  149.  
  150. static    int    Quick_B;                    /* True if Quick B in effect */
  151. static    int    Use_CRC;                    /* True if CRC in effect */
  152. static    int    buffer_size;                /* Our_BS * 4 */
  153. static    int    SA_Max;                        /* 1 if SA not enabled, else MAX_SA */
  154. static    int    SA_Enabled;                    /* True if Send-Ahead is permitted  */
  155. static    int    ack_SA;                        /* Which SA_Buf is waiting for ACK */
  156. static    int    fill_SA;                    /* Which SA_Buf is ready, new data */
  157. static    int    SA_Waiting;                    /* Num of SA_Buf's waiting for ACK */
  158. static  int blkct;                      /* block counter for display */
  159. extern  char strbuf[];                  /* defined in qbttl */
  160.  
  161. static    void do_transport_parameters(void);
  162. static int    send_packet();
  163. static    int    SA_Flush();
  164.  
  165. /*
  166. ** crc
  167. **
  168. ** Calculates XMODEM-style CRC (uses the CCITT V.41 polynomial but
  169. ** completely backwards from the normal bit ordering).
  170. */
  171.  
  172.  
  173. static    unsigned    crc_table[] =
  174. {
  175.     0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
  176.     0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
  177.     0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
  178.     0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
  179.     0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
  180.     0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
  181.     0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
  182.     0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
  183.     0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
  184.     0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
  185.     0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
  186.     0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
  187.     0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
  188.     0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
  189.     0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
  190.     0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
  191.     0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
  192.     0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
  193.     0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
  194.     0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
  195.     0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
  196.     0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  197.     0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
  198.     0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
  199.     0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
  200.     0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
  201.     0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
  202.     0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
  203.     0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
  204.     0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
  205.     0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
  206.     0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
  207. };
  208.  
  209. static    unsigned int    crc_16;
  210.  
  211. /*
  212. ** Upd_CRC updates crc_16 and returns the updated value.
  213. */
  214.  
  215. static    unsigned int    upd_CRC (value)
  216. unsigned int    value;
  217. {
  218.     crc_16 = crc_table [((crc_16 >> 8) ^ (value)) & 0xff] ^    (crc_16 << 8);
  219.     return( crc_16 );
  220. }
  221.  
  222. /*
  223. ** Update the checksum/CRC
  224. */
  225.  
  226. static    void    do_checksum(c)
  227. int    c;
  228. {
  229.     if (Quick_B && Use_CRC)
  230.         lchecksm = upd_CRC (c);
  231.     else
  232.     {
  233.         lchecksm = lchecksm << 1;
  234.  
  235.         if (lchecksm > 255)
  236.             lchecksm = (lchecksm & 0xFF) + 1;
  237.  
  238.         lchecksm = lchecksm + c;
  239.  
  240.         if (lchecksm > 255)
  241.             lchecksm = (lchecksm & 0xFF) + 1;
  242.     }
  243. }
  244.  
  245. static    void    send_failure( code )
  246. int    code;
  247. {
  248.     register PACKET    *p;
  249.  
  250.     ack_SA = 0;
  251.     fill_SA = 0;
  252.     SA_Waiting = 0;
  253.  
  254.     p = &SA_Buf [0];
  255.     p->buf[0] = 'F';
  256.     p->buf[1] = code;
  257.  
  258.     if ( send_packet (1))
  259.         SA_Flush();   /* Gotta wait for the host to ACK it */
  260. }
  261.  
  262. /*
  263. ** bp_ENQ is called when the terminal emulator receives the character <ENQ>
  264. ** from the host.  Its purpose is to initialize for B Protocol and tell the
  265. ** host that we support Quick B.
  266. */
  267.  
  268. void    bp_ENQ()
  269. {
  270.     seq_num = 0;
  271.     buffer_size = 511;               /* Set up defaults */
  272.     Quick_B     = FALSE;             /* Not Quick B Protocol */
  273.     Use_CRC     = FALSE;             /* Not CRC_16      */
  274.     SA_Enabled  = FALSE;             /* No Send-Ahead by us */
  275.     SA_Max      = 1;                 /* = single packet sent */
  276.  
  277.     lc_put (port, DLE);
  278.     lc_put (port, '+');
  279.  
  280.     lc_put (port, DLE);
  281.     lc_put (port, '0');
  282. }
  283.  
  284. /*
  285. ** bp_ESC_I is called when <ESC><I> is received by the terminal emulator.
  286. ** Note that Quick B allows +XX to be added to the end of the response, where
  287. ** XX is the two hex digits of the standard B Protocol checksum of the
  288. ** preceeding characters in the response.  The Qbttl program also supports
  289. ** standard VIDTEX cursor control.
  290. */
  291. static    char    esc_I_response[] = "#VCO,CC,PB,DT,+";
  292.  
  293. void    bp_ESC_I()
  294. {
  295.     int    save_Use_CRC;
  296.     register int    i;
  297.  
  298.     save_Use_CRC = Use_CRC;
  299.     Use_CRC = FALSE;
  300.     lchecksm = 0;
  301.  
  302.     i = 0;
  303.     while( esc_I_response[i] )
  304.     {
  305.         lc_put(port, esc_I_response [i]);
  306.         do_checksum (esc_I_response [i]);
  307.         i++;
  308.     }
  309.  
  310. /*
  311. ** Append two hex digits of checksum to response
  312. */
  313.  
  314.     lc_put(port,  hex_digit[ (lchecksm >> 4) & 0x0F ]);
  315.     lc_put(port,  hex_digit[ lchecksm & 0x0F ] );
  316.     lc_put(port, CR);
  317.  
  318.     Use_CRC = save_Use_CRC;
  319. }
  320.  
  321.  
  322. static    void    send_masked_byte(c)
  323. int    c;
  324. {
  325.     c = c & 0xFF;
  326.  
  327.     if (c < 32)
  328.     {
  329.         if (mask_table [c] != 0)
  330.         {
  331.             lc_put(port, DLE);
  332.             lc_put(port, c + '@');
  333.         }
  334.         else
  335.             lc_put(port, c);
  336.     }
  337.     else
  338.         lc_put(port, c);
  339.  
  340.     s_counter = (s_counter + 1) % 512;
  341. }
  342.  
  343. static    void    send_ack()
  344. {
  345.     lc_put(port, DLE);
  346.     lc_put(port, seq_num + '0');
  347. }
  348.  
  349.  
  350. static    int    read_byte()
  351. {
  352.     timed_out = FALSE;
  353.  
  354.     cchar = wait(port, 10);
  355.  
  356.     if (cchar < 0 )
  357.         return( FALSE );
  358.  
  359.     r_counter = (r_counter + 1) % 512;
  360.     return( TRUE );
  361. }
  362.  
  363.  
  364. static    int    read_masked_byte()
  365. {
  366.     masked = FALSE;
  367.  
  368.     if (read_byte() == FALSE)
  369.         return( FALSE );
  370.  
  371.     if (cchar == DLE)
  372.     {
  373.         if (read_byte() == FALSE)
  374.             return( FALSE );
  375.         cchar &= 0x1F;
  376.         masked = TRUE;
  377.     }
  378.  
  379.     return( TRUE );
  380. }
  381.  
  382. static    int    read_packet (lead_in_seen, from_send_packet)
  383. int    lead_in_seen, from_send_packet;
  384. /*
  385. ** Lead_in_Seen is TRUE if the <DLE><B> has been seen already.
  386. ** from_send_packet is TRUE if called from Send_Packet
  387. **    (causes exit on first error detected)
  388. **
  389. ** Returns True if packet is available from host.
  390. */
  391. {
  392.     int    State, next_seq, block_num, errors, new_cks;
  393.     int    i;
  394.  
  395.     packet_received = FALSE;
  396.     for(i=0; i<buffer_size; i++ )
  397.         r_buffer[i] = 0;
  398.     next_seq = (seq_num +  1) % 10;
  399.     errors = 0;
  400.  
  401.     if (lead_in_seen)        /* Start off on the correct foot */
  402.         State = R_GET_SEQ;
  403.     else
  404.         State = R_GET_DLE;
  405.  
  406.     while (TRUE)
  407.     {
  408.         switch  (State)
  409.         {
  410.             case R_GET_DLE :
  411.                 if (_abort_flag)
  412.                 {
  413.                     send_failure ('A');
  414.                     return( FALSE );
  415.                 }
  416.  
  417.                 if (!read_byte())
  418.                     State = R_TIMED_OUT;
  419.                 else
  420.                     if ((cchar & 0x7F) == DLE)
  421.                         State = R_GET_B;
  422.                     else
  423.                         if ((cchar & 0x7F) == ENQ)
  424.                             State = R_SEND_ACK;
  425.                 break;
  426.  
  427.             case R_GET_B :
  428.                 if (!read_byte())
  429.                     State = R_TIMED_OUT;
  430.                 else
  431.                     if ((cchar & 0x7F) == 'B')
  432.                         State = R_GET_SEQ;
  433.                     else
  434.                         if (cchar == ENQ)
  435.                             State = R_SEND_ACK;
  436.                         else
  437.                             State = R_GET_DLE;
  438.                 break;
  439.  
  440.             case R_GET_SEQ :
  441.                 if (!read_byte())
  442.                     State = R_TIMED_OUT;
  443.                 else
  444.                     if (cchar == ENQ)
  445.                         State = R_SEND_ACK;
  446.                     else
  447.                     {
  448.                         if (Quick_B && Use_CRC)
  449.                             lchecksm = crc_16 = -1;
  450.                         else
  451.                             lchecksm = 0;
  452.  
  453.                         block_num = cchar - '0';
  454.  
  455.                         do_checksum(cchar);
  456.  
  457.                         i = 0;
  458.                         State = R_GET_DATA;
  459.                     }
  460.                 break;
  461.  
  462.             case R_GET_DATA :
  463.                 r_counter = 0;
  464.                 if (!read_masked_byte())
  465.                     State = R_TIMED_OUT;
  466.                 else
  467.                     if ((cchar == ETX) && !masked)
  468.                     {
  469.                         do_checksum(ETX);
  470.                         State = R_GET_CHECKSUM;
  471.                     }
  472.                     else
  473.                     {
  474.                         r_buffer[i] = cchar;
  475.                         i = i + 1;
  476.                         do_checksum(cchar);
  477.                     }
  478.                 break;
  479.  
  480.             case R_GET_CHECKSUM :
  481.                 if (!read_masked_byte())
  482.                     State = R_TIMED_OUT;
  483.                 else
  484.                 {
  485.                     if (Quick_B && Use_CRC)
  486.                     {
  487.                         lchecksm = upd_CRC (cchar);
  488.  
  489.                         if (!read_masked_byte())
  490.                             new_cks = lchecksm ^ 0xFF;
  491.                         else
  492.                         {
  493.                             lchecksm = upd_CRC (cchar);
  494.                             new_cks = 0;
  495.                         }
  496.                     }
  497.                     else
  498.                         new_cks = cchar;
  499.  
  500.                     if (new_cks != lchecksm)
  501.                         State = R_TIMED_OUT;
  502.                     else
  503.                         if (r_buffer[0] == 'F') /* Watch for Failure Packet */
  504.                             State = R_SUCCESS;  /* which is always accepted */
  505.                         else
  506.                             if (block_num == seq_num) /* Watch for dup block */
  507.                                 State = R_SEND_ACK;
  508.                             else
  509.                                 if (block_num != next_seq)
  510.                                     State = R_TIMED_OUT; /* Bad sequence number */
  511.                                 else
  512.                                     State = R_SUCCESS;
  513.                 }
  514.                 break;
  515.  
  516.             case R_TIMED_OUT :
  517.                 errors = errors + 1;
  518.  
  519.                 if ((errors > MAX_ERRORS) || (from_send_packet))
  520.                     return( FALSE );
  521.  
  522.                 lc_put(port, NAK);
  523.  
  524.                 if (from_send_packet)
  525.                     return( FALSE );
  526.  
  527.                 State = R_GET_DLE;
  528.                 break;
  529.  
  530.             case R_SEND_ACK :
  531.                 send_ack();
  532.                 State = R_GET_DLE;        /* wait for the next block */
  533.                 break;
  534.  
  535.             case R_SUCCESS :
  536.                 seq_num = block_num;
  537.                 r_size = i;
  538.                 packet_received = TRUE;
  539.                 return( TRUE );
  540.         }
  541.     }
  542. }
  543.  
  544. static    void    send_data (Buffer_Number)
  545. int    Buffer_Number;
  546. {
  547.     int    i;
  548.     register PACKET    *p;
  549.  
  550.     s_counter = 0;
  551.     p = &SA_Buf [Buffer_Number];
  552.     if (Quick_B && Use_CRC)
  553.         lchecksm = crc_16 = -1;
  554.     else
  555.         lchecksm = 0;
  556.  
  557.     lc_put(port, DLE);
  558.     lc_put(port, 'B');
  559.  
  560.     lc_put(port, p->seq + '0');
  561.     do_checksum(p->seq + '0');
  562.  
  563.     for (i = 0; i<=p->num; i++ )
  564.     {
  565.         send_masked_byte(p->buf[i]);
  566.         do_checksum(p->buf[i]);
  567.     }
  568.  
  569.     lc_put(port, ETX);
  570.     do_checksum (ETX);
  571.  
  572.     if (Quick_B && Use_CRC)
  573.         send_masked_byte (lchecksm >> 8);
  574.  
  575.     send_masked_byte(lchecksm);
  576. }
  577.  
  578. /*
  579. ** ReSync is called to restablish syncronism with the remote.  This is
  580. ** accomplished by sending <ENQ><ENQ> and waiting for the sequence
  581. ** <DLE><d><DLE><d> to be received, ignoring everything else.
  582. **
  583. ** Return is -1 on time out, else the digit <d>.
  584. */
  585. #define    GET_FIRST_DLE        1
  586. #define    GET_FIRST_DIGIT        2
  587. #define    GET_SECOND_DLE        3
  588. #define    GET_SECOND_DIGIT    4
  589.  
  590. static    int    ReSync()
  591. {
  592.     int    State, Digit_1;
  593.  
  594.     lc_put(port, ENQ);     /* Send <ENQ><ENQ> */
  595.     lc_put(port, ENQ);
  596.     State = GET_FIRST_DLE;
  597.  
  598.     while(1)
  599.     {
  600.         switch (State)
  601.         {
  602.             case GET_FIRST_DLE :
  603.                 if( !read_byte() )
  604.                     return( -1 );
  605.                 if( cchar == DLE )
  606.                     State = GET_FIRST_DIGIT;
  607.                 break;
  608.             case GET_FIRST_DIGIT :
  609.                 if( !read_byte() )
  610.                     return( -1 );
  611.                 if( (cchar >= '0') && (cchar <= '9') )
  612.                 {
  613.                     Digit_1 = cchar;
  614.                     State = GET_SECOND_DLE;
  615.                 }
  616.                 break;
  617.             case GET_SECOND_DLE :
  618.                 if( !read_byte() )
  619.                     return( -1 );
  620.                 if( cchar == DLE )
  621.                     State = GET_SECOND_DIGIT;
  622.                 break;
  623.             case GET_SECOND_DIGIT :
  624.                 if( !read_byte() )
  625.                     return( -1 );
  626.                 if( (cchar >= '0') && (cchar <= '9') )
  627.                 {
  628.                     if( Digit_1 == cchar )
  629.                         return( cchar );
  630.                     else
  631.                     {
  632.                         Digit_1 = cchar;
  633.                         State = GET_SECOND_DLE;
  634.                     }
  635.                 }
  636.                 else
  637.                     State = GET_SECOND_DLE;
  638.                 break;
  639.         }
  640.     }
  641. }
  642.  
  643. /*
  644. ** get_ACK is called to wait until the SA_Buf indicated by ack_SA
  645. ** has been ACKed by the host.
  646. */
  647. static    int    get_ACK()
  648. {
  649.     int    State, errors, block_num, i;
  650.     int    Sent_ENQ;
  651.     int    SA_Index;
  652.  
  653.     packet_received = FALSE;
  654.     errors = 0;
  655.     Sent_ENQ = FALSE;
  656.     State = S_GET_DLE;
  657.  
  658.     while( TRUE )
  659.     {
  660.         switch (State) {
  661.         case S_GET_DLE :
  662.             if (_abort_flag)
  663.             {
  664.                 send_failure ('A');
  665.                 return( FALSE );
  666.             }
  667.  
  668.             if (!read_byte())
  669.                 State = S_TIMED_OUT;
  670.             else if (cchar == DLE)
  671.                 State = S_GET_NUM;
  672.             else if (cchar == NAK)
  673.             {
  674.                 if (++errors > MAX_ERRORS)
  675.                     return( FALSE );
  676.                 State = S_SEND_ENQ;
  677.             }
  678.             else if (cchar == ETX)
  679.                 State = S_SEND_NAK;
  680.             break;
  681.  
  682.         case S_GET_NUM :
  683.             if (!read_byte())
  684.                 State = S_TIMED_OUT;
  685.             else if ((cchar >= '0') && (cchar <= '9'))
  686.                 State = S_HAVE_ACK;    /* Received ACK */
  687.             else if (cchar == 'B')
  688.                 State = S_GET_PACKET; /* Try to get packet */
  689.             else if (cchar == NAK)
  690.             {
  691.                 if (++errors > MAX_ERRORS)
  692.                     return( FALSE );
  693.                 State = S_SEND_ENQ;
  694.             }
  695.             else
  696.                 State = S_TIMED_OUT;
  697.             break;
  698.  
  699.         case S_GET_PACKET :
  700.             if (read_packet (TRUE, TRUE))
  701.             {
  702.                 if (r_buffer [0] == 'F')
  703.                 {
  704.                     send_ack();
  705.                     return( FALSE );
  706.                 }
  707.                 else
  708.                     return( TRUE );
  709.             }
  710.  
  711.             State = S_TIMED_OUT; /* On a bad receive, try again */
  712.             break;
  713.         case S_HAVE_ACK:
  714.             block_num = cchar - '0';
  715.             if (SA_Buf [ack_SA].seq == block_num)
  716.             {    /* This is the one we're waiting for */
  717.                 ack_SA = incr_SA(ack_SA);
  718.                 SA_Waiting--;
  719.                 return( TRUE );
  720.             }
  721.             else
  722.                 if (SA_Buf [incr_SA (ack_SA)].seq == block_num)
  723.                 {    /* Must have missed an ACK */
  724.                     ack_SA = incr_SA (ack_SA);
  725.                     ack_SA = incr_SA (ack_SA);
  726.                     SA_Waiting -= 2;
  727.                     return( TRUE );
  728.                 }
  729.                 else 
  730.                     if (SA_Buf [ack_SA].seq == incr_seq (block_num))
  731.                     {
  732.                         if( Sent_ENQ )
  733.                             State = S_SEND_DATA;
  734.                         else
  735.                             State = S_GET_DLE;
  736.                     }
  737.                     else
  738.                         State = S_TIMED_OUT;
  739.             Sent_ENQ = FALSE;
  740.             break;
  741.         case S_TIMED_OUT :
  742.             if (++errors > MAX_ERRORS)
  743.                 return( FALSE );
  744.  
  745.             State = S_SEND_ENQ;
  746.             break;
  747.  
  748.         case S_SEND_NAK :
  749.             if (++errors > MAX_ERRORS)
  750.                 return( FALSE );
  751.  
  752.             lc_put(port, NAK);
  753.  
  754.             State = S_GET_DLE;
  755.             break;
  756.  
  757.         case S_SEND_ENQ :
  758.             if (++errors > MAX_ERRORS)
  759.                 return( FALSE );
  760.             cchar = ReSync();
  761.             if( cchar == -1 )
  762.                 State = S_SEND_ENQ;
  763.             else
  764.                 State = S_HAVE_ACK;
  765.             Sent_ENQ = TRUE;
  766.             break;
  767.  
  768.         case S_SEND_DATA :
  769.             SA_Index = ack_SA;
  770.  
  771.             for (i = 1; i<=SA_Waiting; i++ )
  772.             {
  773.                 send_data (SA_Index);
  774.                 SA_Index = incr_SA (SA_Index);
  775.             }
  776.  
  777.             State = S_GET_DLE;
  778.             Sent_ENQ = FALSE;
  779.             break;
  780.         }
  781.     }
  782. } /* get_ACK */
  783.  
  784. static int    send_packet (size)
  785. int    size;
  786. {
  787.     if (SA_Waiting == SA_Max)
  788.         if (!get_ACK())
  789.             return( FALSE );
  790.  
  791.     seq_num = incr_seq (seq_num);
  792.     SA_Buf [fill_SA].seq = seq_num;
  793.     SA_Buf [fill_SA].num = size;
  794.     send_data (fill_SA);
  795.     fill_SA = incr_SA (fill_SA);
  796.     SA_Waiting = SA_Waiting + 1;
  797.     return( TRUE );
  798. }
  799. /*
  800. ** SA_Flush is called after sending the last packet to get host's
  801. ** ACKs on outstanding packets.
  802. */
  803. static    int    SA_Flush()
  804. {
  805.     while( SA_Waiting != 0 )
  806.         if (!get_ACK())
  807.             return( FALSE );
  808.     return( TRUE );
  809. }
  810.  
  811. /* Send_File is called to send a file to the host */
  812. static    int    send_file(name)
  813. char    name[];
  814. {
  815.     int    fd;
  816.     int    n;
  817.     register PACKET    *p;
  818.  
  819.     fd = open(name, (O_BINARY | O_RDONLY));
  820.  
  821.     if (fd < 0)
  822.       {
  823.         send_failure('E');
  824.         urgentmsg ("ERROR","** Cannot find that file **");
  825.         return( FALSE );
  826.     }
  827.  
  828.     do
  829.     {
  830.         p = &SA_Buf [fill_SA];
  831.         p->buf[0] = 'N';
  832.         n = read(fd, &p->buf[1], buffer_size);
  833.  
  834.         if (n > 0)
  835.         {
  836.             if (send_packet (n) == FALSE)
  837.                 return( FALSE );
  838.             sprintf(strbuf, "Sent Block: %d", blkct++);
  839.             atsay(4,1,strbuf);
  840.         }
  841.     } while( n == buffer_size );
  842.  
  843.     close (fd);
  844.  
  845.     if (n < 0)
  846.     {
  847.         send_failure ('E');
  848.         urgentmsg ("ERROR", "** Read failure...aborting **");
  849.         return(FALSE);
  850.     }
  851.  
  852. /* Inform host that the file was sent */
  853.     p = &SA_Buf [fill_SA];
  854.     p->buf[0] = 'T';
  855.     p->buf[1] = 'C';
  856.  
  857.     if (send_packet(2) == FALSE)
  858.         return( FALSE );
  859.     else
  860.     {
  861.         say( "Waiting for host..." );
  862.         if (!SA_Flush())
  863.             return( FALSE );
  864.         return( TRUE );
  865.     }
  866. }
  867.  
  868. /*
  869. ** do_transport_parameters is called when a Packet type of + is received.
  870. ** It sends a packet of our local Quick B parameters and sets the Our_xx
  871. ** parameters to the minimum of the sender's and our own parameters.
  872. */
  873. static    void do_transport_parameters()
  874. {
  875.     register PACKET    *p;
  876.  
  877.     His_WS = r_buffer [1];     /* Pick out Sender's parameters */
  878.     His_WR = r_buffer [2];
  879.     His_BS = r_buffer [3];
  880.     His_CM = r_buffer [4];
  881.  
  882.     p = &SA_Buf [fill_SA];
  883.     p->buf [0] = '+';  /* Prepare to return our own parameters */
  884.     p->buf [1] = DEF_WS;
  885.     p->buf [2] = DEF_WR;
  886.     p->buf [3] = DEF_BS;
  887.     p->buf [4] = DEF_CM;
  888.     p->buf [5] = DEF_DQ;
  889.  
  890.     if (!send_packet (5))
  891.         return;
  892.  
  893.     if (SA_Flush())                 /* Wait for host's ACK on our packet */
  894.     {
  895. /* Take minimal subset of Transport Params. */
  896. /* If he can send ahead, we can receive it. */
  897.         Our_WR = (His_WS < DEF_WR) ? His_WS : DEF_WR;
  898.  
  899. /* If he can receive send ahead, we can send it. */
  900.         Our_WS = (His_WR < DEF_WS) ? His_WR : DEF_WS;
  901.  
  902.         Our_BS = His_BS < DEF_BS ? His_BS : DEF_BS;
  903.  
  904.         Our_CM = His_CM < DEF_CM ? His_CM : DEF_CM;
  905.  
  906.         if (Our_BS == 0)
  907.             Our_BS = 4;    /* Default */
  908.  
  909.         buffer_size = Our_BS * 128;
  910.  
  911.         Quick_B = TRUE;
  912.  
  913.         if (Our_CM == 1)
  914.             Use_CRC = TRUE;
  915.  
  916.         if (Our_WS != 0)
  917.         {
  918.             SA_Enabled = TRUE;
  919.             SA_Max     = MAX_SA;
  920.         }
  921.     }
  922. }
  923.  
  924. /*
  925.   do_application_parameters is called when a ? packet is received.
  926.   This version ignores the host's packet and returns a ? packet
  927.   saying that normal B Protocol File Transfer is supported.
  928.   (Well, actually it says that no extended application packets are
  929.    supported.  The T packet is assumed to be standard.) */
  930.  
  931. static    void    do_application_parameters()
  932. {
  933.     register PACKET    *p;
  934.  
  935.     p = &SA_Buf [fill_SA];
  936.     p->buf[0] = '?';     /* Build the ? packet */
  937.     p->buf[1] = 1;             /* The T packet flag  */
  938.  
  939.     if (send_packet (1))            /* Send the packet    */
  940.         SA_Flush();
  941. }
  942.  
  943. /* Receive_File is called to receive a file from the host */
  944. static    int    receive_file (name)
  945. char    name[];
  946. {
  947.     int    fd;
  948.     unsigned  bytes;
  949.  
  950.     _fmode = O_BINARY;
  951.     fd = creat(name,(S_IREAD | S_IWRITE) );
  952.  
  953.     if (fd < 0)
  954.     {
  955.         urgentmsg ("ERROR", "** Cannot open file...aborting **");
  956.         send_failure('E');
  957.         return( FALSE );
  958.     }
  959.  
  960.     send_ack();
  961.  
  962. /* Process each incoming packet until 'TC' packet received or failure */
  963.  
  964.     while( TRUE )
  965.     {
  966.         if (read_packet (FALSE, FALSE))
  967.         {
  968.             switch (r_buffer[0]) {
  969.             case 'N' :
  970.                 bytes = r_size - 1;
  971.  
  972.                 if (write(fd, &r_buffer[1], bytes) != bytes )
  973.                 {
  974.                     urgentmsg ("ERROR", "** Write failure...aborting **");
  975.                     close (fd);
  976.                     send_failure ('E');
  977.                     return( FALSE );
  978.                 }
  979.                 send_ack();
  980.                 sprintf(strbuf, "Received Block: %d", blkct++);
  981.                 atsay(4,1,strbuf);
  982.                 break;
  983.  
  984.             case 'T' :
  985.                 if (r_buffer[1] == 'C')
  986.                 {
  987.                     close(fd);
  988.  
  989.                     send_ack();
  990.                     return( TRUE );
  991.                 }
  992.                 else
  993.                 {
  994.                     urgentmsg ("ERROR", "** Invalid termination packet...aborting **");
  995.                     close (fd);
  996.                     send_failure ('N');
  997.                     return( FALSE );
  998.                 }
  999.  
  1000.             case 'F' :
  1001.                 send_ack();
  1002.                 urgentmsg ("ERROR","** Failure packet received...aborting **");
  1003.                 close (fd);
  1004.                 return( FALSE );
  1005.             }
  1006.         }
  1007.          else
  1008.         {
  1009.             urgentmsg ("ERROR", "** Failed to receive packet...aborting **");
  1010.             close (fd);
  1011.             return( FALSE );
  1012.         }
  1013.     }
  1014. }
  1015.  
  1016. /*
  1017. ** bp_DLE is called from the main program when the character <DLE> is
  1018. ** received from the host.
  1019. **
  1020. ** This routine calls read_packet and dispatches to the appropriate
  1021. ** handler for the incoming packet.
  1022. */
  1023. void    bp_DLE()
  1024. {
  1025.     int    i;
  1026.     char    filename[255];
  1027.     char    str[2];
  1028. /*
  1029. ** Begin by getting the next character.  If it is <B> then enter the
  1030. ** B_Protocol state.  Otherwise simply return.
  1031. */
  1032.  
  1033.     if (wait (port, 10) != 'B')
  1034.         return;
  1035.  
  1036.     strcpy( str, " " );
  1037.  
  1038.     ack_SA  = 0;    /* Initialize Send-ahead variables */
  1039.     fill_SA = 0;
  1040.     SA_Waiting      = 0;
  1041.     blkct = 0;
  1042.     erase();                    /* clear the window */
  1043.  
  1044. /*  <DLE><B> received; begin B Protocol */
  1045.  
  1046.     r_counter   = 0;
  1047.     s_counter   = 0;
  1048.  
  1049.     if (Quick_B)
  1050.     {
  1051.         say ("*** Quick B is in effect ***\r");
  1052.  
  1053.         if (Use_CRC)
  1054.             say ("*** Using CRC ***\r");
  1055.  
  1056.         if (Our_WS != 0) /* Allow send-ahead if other end agrees */
  1057.             say ("*** Send-Ahead enabled ***\r");
  1058.     }
  1059.  
  1060.     if (read_packet (TRUE, FALSE))
  1061.     {
  1062. /* Dispatch on the type of packet just received */
  1063.  
  1064.             switch (r_buffer[0]) {
  1065.         case 'T':     /* File Transfer Application */
  1066.             switch (r_buffer[1]) {
  1067.             case 'D' :    /* downloading */
  1068.                 break;
  1069.             case 'U' :    /* uploading */
  1070.                 break;
  1071.             default :
  1072.                 send_failure('N');
  1073.                 return;
  1074.             }
  1075.  
  1076.             switch (r_buffer[2]) {
  1077.             case 'A':    /* ascii file */
  1078.                 break;
  1079.             case 'B':    /* binary file */
  1080.                 break;
  1081.             default :
  1082.                 send_failure('N');        /* not implemented */
  1083.                 return;
  1084.             }
  1085.  
  1086.             i = 2;
  1087.             strcpy( filename, "" );
  1088.  
  1089.             while( (r_buffer[i] != 0) && (i < r_size) )
  1090.             {
  1091.                 i = i + 1;
  1092.                 str[0] = r_buffer[i];
  1093.                 strcat( filename, str );
  1094.             }
  1095.  
  1096.             if (r_buffer[1] == 'U')
  1097.             {
  1098.                 if( send_file(filename) )
  1099.                     urgentmsg("SUCCESS", "Transfer completed!" );
  1100.             }
  1101.             else
  1102.             {
  1103.                 if( receive_file(filename) )
  1104.                     urgentmsg("SUCCESS", "Transfer completed!" );
  1105.             }
  1106.             break;
  1107.  
  1108.         case '+':          /* Received Transport Parameters Packet */
  1109.             do_transport_parameters();
  1110.             break;
  1111.  
  1112.         case '?':          /* Received Application Parameters Packet */
  1113.             do_application_parameters();
  1114.             break;
  1115.  
  1116.         default:    /* Unknown packet; tell host we don't know */
  1117.             send_failure ('N');
  1118.                     break;
  1119.  
  1120.         }  /* of case */
  1121.     }     /* of if read_packet the */
  1122. }
  1123.